在JS的其中一個重要觀念是當創造一個變數var a;他會佔據一個記憶體位置,而當賦予給他值的時候a = 1;會把a的記憶體位置拷貝並且指向這個純質(1)。
這觀念或許很抽象,白話來講創造變數的時候他會是一個空白的記憶體,當你賦予它值var a = 1;的時候他會去拷貝1這個純質。
那什麼是by value和by reference呢?我們先來看最簡單的by value。
by value
只要給變數
純質(primitive),例如數值、字串、布林值等非物件的東西會產生by value這個動作。
我們直接看看例子:1
2
3
4
5var a = 1;
var b = a;
a = 2;
console.log(a);  //print 2
console.log(b);  //print 1
答案非常的直覺,但底下發生了什麼事情?
首先我們的程式碼會先產生Hoisting(創造與提升)這個動作,讓a和b各自有一個記憶體空間,賦予a等於純質1,記憶體拷貝並指向了這個純質。
再來b = a;的時候因為a的記憶體剛剛拷貝和指向了一個純質,所以b的記憶體也拷貝並指向了相同的純質,這時候!!雖然a和b的記憶體指向完全一模一樣的純質,但由於by value的行為其實a和b的記憶體位置是不一樣的!!!
白話譬喻的話就是a買了一棟信義區的房子,此時b說要買跟a一樣的房子,所以他們都有一模一樣在信義區的房子,但是地址是不一樣的,這就是by value的行為,非常好懂,再來我們看看by reference。
by reference
只要給物件(function算是物件)的東西會產生
by reference這個動作。
再來直接參考下面的例子:1
2
3
4
5var a = { greeting: 'Hi'};
var b = a;
a.greeting = 'Bye';
console.log(a);  //print Object { greeting: "Bye" }
console.log(b);  //print Object { greeting: "Bye" }
直接看結果我們發現b竟然跟a直接同化了!!發生了什麼事情?
比照剛剛by value的行為即使讓b直接等於a取得一模一樣的純質,但是b的記憶體位置是一個新的位置!
相反的by reference的行為並不會給b一個新的記憶體位置,所以直接變動a或者是b物件裡面的東西它們都會一起受影響,因為他們就是住在同一個屋簷底下。
想同的規則即使是在function裡面的參數(parameter)也是一樣
直接看例子:1
2
3
4
5
6
7
8
9
10
11var a = { greeting: 'Hi'};
var b = a;
a.greeting = 'Bye';
console.log(a);  //print Object { greeting: "Bye" }
console.log(b);  //print Object { greeting: "Bye" }
function changeName (obj) {
  obj.greeting = 'morning';
}
changeName(b);
console.log(a);  //print Object { greeting: "morning" }
console.log(b);  //print Object { greeting: "morning" }
傳入changeName的參數會改動參數裡greeting的值變為morning,由於by reference的行為a也被我同步了!
如果是用物件實體(object literal)的方式指定物件的值,那麼會是by value
直接看例子:1
2
3
4
5var a = { greeting: 'Hi'};
var b = a;
b = { greeting:'Bye' };
console.log(a);  //print Object { greeting: "Hi" }
console.log(b);  //print Object { greeting: "Bye" }
結果不會同步!!
因為b = { greeting:'Bye' };這行等同於b自己創造了一了新的物件,所以b和a已經不是共用同一個記憶體位置了,簡單的說b已經不和a住在同一個屋簷下,b自己買了新房子了!
如果是用b.greeting = 'Bye';這種方法是更改物件裡面的內容,也就是還在同一個屋簷下但是做了裝潢,當然兩個同居的人就會享有一樣的效果,這就是by value和by reference的行為。
了解了這個在規劃的時候要盡量避免踩上這些地雷,所以在操縱變數的時候要注意一下這些觀念,不然這算是非常難degug的東西,尤其在angular的$scope運用會死得很慘XD。